package com.liachen.stock.ext.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.liachen.common.constant.Constant;
import com.liachen.common.enums.UserType;
import com.liachen.common.util.ToolsUtil;
import com.liachen.stock.entity.StockInfo;
import com.liachen.stock.entity.StockSimple;
import com.liachen.stock.entity.StockSummaryInfo;
import com.liachen.stock.entity.User;
import com.liachen.stock.entity.UserStockInfo;
import com.liachen.stock.ext.THSExtService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * @author EDY
 */
@Slf4j
@Service
public class THSExtServiceImpl implements THSExtService {
    private static final String THS_HOST = "http://moni.10jqka.com.cn/%s";
    private static final String WENCAI_HOST = "https://www.iwencai.com";
    private static final String THS_STOCK_HOST = "http://stockpage.10jqka.com.cn/realHead_v2.html#hs_%s";
    private static final String ADD_FOLLOW_URL = "mncg/index/addzzgs/";
    private static final String GET_STOCK_DATA_LIST_URL = "/gateway/urp/v7/landing/getDataList";
    private static final String COOKIE_STR = "other_uid=Ths_iwencai_Xuangu_dmcjx5j5xvgwecoe03sjahyzr4lt20ex; ta_random_userid=sh5hwf4xxv; cid=abed9547ca1d93df10243599e1aef5821712306946; u_ukey=A10702B8689642C6BE607730E11E6E4A; u_uver=1.0.0; u_dpass=JYwN3QxasedM%2F8sJ2PJXUgL5qq1be8b12HhzOo8d9aJY07jWhl2iFhg9sKEJwgcnHi80LrSsTFH9a%2B6rtRvqGg%3D%3D; u_did=61D5C7033C644495987F0936542DDEAB; u_ttype=WEB; ttype=WEB; user=MDrM7ND80Me602xjOjpOb25lOjUwMDoxNTM3NDIzMDY6NywxMTExMTExMTExMSw0MDs0NCwxMSw0MDs2LDEsNDA7NSwxLDQwOzEsMTAxLDQwOzIsMSw0MDszLDEsNDA7NSwxLDQwOzgsMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEsNDA7MTAyLDEsNDA6Mjc6OjoxNDM3NDIzMDY6MTcxNzgwMTU1NTo6OjEzNDg1ODIzODA6NjA0ODAwOjA6MWJhMjVlZDcwOTVjNDZjN2FhMGViMWMxMDAwOTE4OGRmOmRlZmF1bHRfNDow; userid=143742306; u_name=%CC%EC%D0%FC%D0%C7%BA%D3lc; escapename=%25u5929%25u60ac%25u661f%25u6cb3lc; ticket=4088c08355f77284c2f8dba3a6e3dc89; user_status=0; utk=8ce5ae9943d4a838f4256eb2f7af468a; v=A6PmfnZxwbZsgI3dWK4wZh9DNOxImCTqcQp8k9Uf_Nt5s82SXWjHKoH8CwPm";

    @Override
    public List<User> queryUserList(String type) {
        List<User> userList = new ArrayList<>();
        try {
            Document doc = Jsoup.connect(String.format(THS_HOST, UserType.getByType(type).getUrl())).userAgent(Constant.USER_AGENT).cookies(ToolsUtil.getCookie(COOKIE_STR)).get();
            Elements elements = doc.select("table.table_hover_tr > tbody > tr");
            int rankNo = 1;
            for (Element element : elements) {
                userList.add(convertUser(rankNo, element, type));
                rankNo++;
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            log.info("用户列表查询成功，type={}", type);
        }

        return userList;
    }

    @Override
    public List<UserStockInfo> queryUserStockInfoList(Long userId) {
        List<UserStockInfo> userStockInfoList = new ArrayList<>();
        try {
            Document doc = Jsoup.connect(String.format(THS_HOST, userId)).cookies(ToolsUtil.getCookie(COOKIE_STR)).get();
            Elements elements = doc.select("#ccqk_tbl > tbody > tr");
            if (elements.isEmpty()) {
                return userStockInfoList;
            }
            for (Element element : elements) {
                userStockInfoList.add(convertUserStockInfo(userId, element));
            }
        } catch (Exception e) {
            log.error("用户userId:{}, 持仓查询失败, 错误信息：{}", userId, e.getMessage(), e);
        } finally {
            log.info("用户userId:{}, 持仓:{}", userId, JSONUtil.toJsonStr(userStockInfoList));
        }
        return userStockInfoList;
    }

    @Override
    public void followUser(String userId, String usrId, String userName) {
        try {
            Document doc = Jsoup.connect(String.format(THS_HOST, ADD_FOLLOW_URL) + userId).cookies(ToolsUtil.getCookie(COOKIE_STR)).post();
            log.info(doc.text());
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public StockSimple getStockTodayInfo(StockSummaryInfo stockSummaryInfo) throws IOException {
        Document doc = Jsoup.connect(String.format(THS_STOCK_HOST, stockSummaryInfo.getCode())).cookies(ToolsUtil.getCookie(COOKIE_STR)).userAgent(Constant.USER_AGENT).get();
        String increaseStr = doc.select("#hexm_float_rate").first().text();
        StockSimple stockSimple = new StockSimple();
        stockSimple.setCode(stockSummaryInfo.getCode());
        stockSimple.setName(stockSummaryInfo.getName());
        try {
            stockSimple.setIncrease(new BigDecimal(increaseStr));
        } catch (Exception e) {
            stockSimple.setIncrease(BigDecimal.ZERO);
        }
        return stockSimple;
    }

    @Override
    public List<StockInfo> getStockList(Map params) throws IOException {
        Document doc = Jsoup.connect(WENCAI_HOST + GET_STOCK_DATA_LIST_URL)
                .cookies(ToolsUtil.getCookie(COOKIE_STR))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .ignoreContentType(true)
                .userAgent(Constant.USER_AGENT)
                .data(params)
                .post();

        JSONObject jsonObject = JSONUtil.parseObj(doc.text());
        JSONArray jsonArray = jsonObject.getJSONObject("answer").getJSONArray("components").getJSONObject(0).getJSONObject("data").getJSONArray("datas");
        if(jsonArray.isEmpty()){
            return Lists.newArrayList();
        }
        return com.alibaba.fastjson.JSONObject.parseArray(jsonArray.toString(), StockInfo.class);
    }

    public static void main(String[] args) {
        FileUtil.writeString("*****************", "src/test/resources/111.txt","UTF-8");

        String fileStr = FileUtil.readString("src/test/resources/111.txt", "UTF-8");
        log.info(fileStr);
    }

    private UserStockInfo convertUserStockInfo(Long userId, Element element) throws ParseException {
        String code = element.select("td:nth-child(1) > span > a").first().attr("title");
        String name = element.select("td:nth-child(2) > span > a").first().text();
        Integer holdNum = Integer.valueOf(element.select("td:nth-child(3) > span").first().text());
        Date buyTime = DateUtils.parseDate(element.select("td:nth-child(4) > span").first().text(), "yyyy-MM-dd");
        BigDecimal cost = new BigDecimal(element.select("td:nth-child(5) > span").first().text());
        BigDecimal currentPrice = new BigDecimal(element.select("td:nth-child(6) > span").first().text());
        String todayIncreaseStr = element.select("td:nth-child(7) > span").first().text();
        BigDecimal todayIncrease = todayIncreaseStr.contains("%") ? new BigDecimal(StringUtils.removeEnd(todayIncreaseStr, "%")) : BigDecimal.ZERO;
        BigDecimal marketValue = new BigDecimal(element.select("td:nth-child(8) > span").first().text());
        BigDecimal increaseRate = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(9) > span").first().text(), "%"));
        BigDecimal floatingProfit = new BigDecimal(element.select("td:nth-child(10) > span").first().text());
        return new UserStockInfo().setUserId(userId).setCode(code).setName(name).setHoldNum(holdNum).setBuyTime(buyTime).setCost(cost).setCurrentPrice(currentPrice).setTodayIncrease(todayIncrease).setMarketValue(marketValue).setIncreaseRate(increaseRate).setFloatingProfit(floatingProfit).setAddTime(new Date());
    }

    private User convertUser(int rank, Element element, String type) {
        Element userInfo = element.select("td:nth-child(11) > p").first();
        String userId = userInfo.attr("userid");
        String usrId = userInfo.attr("usrid");
        String userName = userInfo.attr("username");
        String tradeInfo = userInfo.text();
        String grade = element.select("td:nth-child(3) > p").text();
        BigDecimal totalGain = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(4) > p").first().text(), "%"));
        BigDecimal monthGain = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(5) > p").first().text(), "%"));
        BigDecimal weekGain = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(6) > p").first().text(), "%"));
        BigDecimal dailyGain = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(7) > p").first().text(), "%"));
        BigDecimal successRate = new BigDecimal(StringUtils.removeEnd(element.select("td:nth-child(8) > p").first().text(), "%"));
        BigDecimal totalAssets = new BigDecimal(element.select("td:nth-child(9) > p").first().text());
        Long follow = Long.valueOf(element.select("td:nth-child(10) > p").first().text());
        return new User().setType(type).setUserId(Long.valueOf(userId)).setUsrId(Long.valueOf(usrId)).setUserName(userName).setRankNo(rank).setGrade(grade).setTotalGain(totalGain).setMonthGain(monthGain).setWeekGain(weekGain).setDailyGain(dailyGain).setSuccessRate(successRate).setTotalAssets(totalAssets).setFollow(follow).setTradeInfo(tradeInfo).setAddTime(new Date());
    }
}
